package com.platform.web.lisenter;

import com.alibaba.fastjson.JSONObject;
import com.platform.base.domain.CollectorInfo;
import com.platform.base.domain.MeterInfo;
import com.platform.base.domain.ValveInfo;
import com.platform.base.service.ICollectorInfoService;
import com.platform.base.service.IMeterInfoService;
import com.platform.base.service.IValveInfoService;
import com.platform.common.manager.AsyncManager;
import com.platform.common.utils.DateUtils;
import com.platform.common.utils.netty.NettyUtil;
import com.platform.common.utils.redis.RedisUtil;
import com.platform.common.utils.spring.SpringUtils;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.TimerTask;

@Component
@Slf4j
public class CollectorListener {

    @Autowired
    private RedisUtil redisUtil;

    @RabbitListener(queues = "collector_queue")
    @RabbitHandler
    public void receiveCollector(JSONObject object, Channel channel, Message message){
        try{
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            String messageId = message.getMessageProperties().getHeaders().get("spring_returned_message_correlation").toString();
            if(redisUtil.hasKey("message:"+messageId)){
                return;
            }
            redisUtil.set("message:"+messageId, messageId, 1000);
            //执行异步保存数据
            log.info("执行异步保存采集器关联设备数据："+ object.getString("datas"));
            AsyncManager.me().execute(CollectorPoolTask.saveCollector(object.getString("datas"), object.getInteger("type")));
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    @RabbitListener(queues = "collector_online_queue")
    @RabbitHandler
    public void receiveCollectorOnline(JSONObject object, Channel channel, Message message){
        try{
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            //执行异步保存数据
            log.info("执行异步保存采集器上线数据："+ object.getString("collectorId"));
            AsyncManager.me().execute(CollectorPoolTask.saveOnline(object.getString("collectorId"), object.getInteger("onlineStatus")));
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

/**
 * 异步任务保存采集器数据
 */
class CollectorPoolTask {

    private static RedisUtil redisUtil;

    private static IMeterInfoService meterInfoService;

    private static IValveInfoService valveInfoService;

    private static ICollectorInfoService collectorInfoService;

    public static TimerTask saveCollector(final String datas, final int type)
    {
        meterInfoService = SpringUtils.getBean(IMeterInfoService.class);

        valveInfoService = SpringUtils.getBean(IValveInfoService.class);

        redisUtil = SpringUtils.getBean(RedisUtil.class);

        return new TimerTask() {
            @Override
            public void run() {
                if(type==1){
                    //获取采集器关联设备
                    String[] msgs = datas.split(" ");
                    saveLink(msgs);
                }else{
                    saveInit(datas);
                }
            }
        };
    }

    public static TimerTask saveOnline(final String collectorId, final int onlineStatus)
    {
        collectorInfoService = SpringUtils.getBean(ICollectorInfoService.class);

        return new TimerTask() {
            @Override
            public void run() {
                CollectorInfo info = new CollectorInfo();
                info.setOnlineStatus(onlineStatus);
                info.setCollectorId(collectorId);
                collectorInfoService.updateCollectorInfo(info);
            }
        };
    }

    /**
     * 将采集到的设备关联信息存放到数据库
     */
    private static void saveLink(String[] datas){
        collectorInfoService = SpringUtils.getBean(ICollectorInfoService.class);
        String clientId = datas[2] + datas[1];
        String edition = NettyUtil.get10HexNum(datas[4]) +"."+ NettyUtil.get10HexNum(datas[5])+"." +NettyUtil.get10HexNum(datas[6]);
        try {
            //还原阀门登记状态
            valveInfoService.updateValveInfoByCollectorId(clientId);
            //还原热表登记状态
            meterInfoService.updateMeterInfoByCollectorId(clientId);
            int datalength = NettyUtil.get10HexNum(datas[9]+ datas[10]);
            if(datalength==0){
                redisUtil.hset(clientId,"0C", "0", 10);
            }else {
                String msgs = NettyUtil.strChange(datas, 11, datalength);
                datas = msgs.split(" ");
                int len = datas.length / 5;
                String[] groups = new String[len];
                int x = 0;
                for (int i = 0; i < datas.length; i++) {
                    if (i != 0 && i % 5 == 0) {
                        x += 1;
                    }
                    if (groups[x] == null) {
                        groups[x] = "";
                    }
                    groups[x] += datas[i] + " ";
                }
                for (String group : groups) {
                    String[] contents = group.split(" ");
                    if (contents[4].equals("00")) {
                        String valveId = contents[3] + contents[2];
                        ValveInfo info = null;
                        if(redisUtil.hHasKey("valve-info", valveId)){
                            info = (ValveInfo) redisUtil.hget("valve-info", valveId);
                        }else{
                            info = valveInfoService.selectValveInfoById(valveId);
                        }
                        if(info == null){
                            info = new ValveInfo();
                            info.setValveId(valveId);
                            info.setCollectorId(clientId);
                            info.setLocationId(1L);
                            info.setRegisterFlag("1");
                            info.setTypeId(1L);
                            info.setCreateBy("admin");
                            info.setCreateTime(DateUtils.getNowDate());
                            valveInfoService.insertValveInfo(info);
                        }else {
                            info.setRegisterFlag("1");
                            info.setCollectorId(clientId);
                            valveInfoService.updateValveInfo(info);
                        }
                    } else {
                        String meterId = contents[0] + contents[1] + contents[2] + contents[3];
                        MeterInfo info = null;
                        if(redisUtil.hHasKey("meter-info", meterId)){
                            info = (MeterInfo) redisUtil.hget("meter-info", meterId);
                        }else{
                            info = meterInfoService.selectMeterInfoById(meterId);
                        }
                        long type = 0;
                        if(contents[4].equals("01")){
                            type = 1;
                        }
                        else if (contents[4].equals("02")){
                            type = 2;
                        }
                        else if (contents[4].equals("03")){
                            type = 3;
                        }
                        else if (contents[4].equals("04")){
                            type = 4;
                        }
                        if(info == null){
                            info = new MeterInfo();
                            info.setMeterId(meterId);
                            info.setCollectorId(clientId);
                            info.setLocationId(1L);
                            info.setRegisterFlag("1");
                            info.setTypeId(type);
                            info.setCreateBy("admin");
                            info.setCreateTime(DateUtils.getNowDate());
                            meterInfoService.insertMeterInfo(info);
                        }else {
                            info.setRegisterFlag("1");
                            info.setCollectorId(clientId);
                            info.setTypeId(type);
                            meterInfoService.updateMeterInfo(info);
                        }
                    }
                }
                CollectorInfo info = collectorInfoService.selectCollectorInfoById(clientId);
                info.setEdition(edition);
                collectorInfoService.updateCollectorInfo(info);

                redisUtil.hset(clientId, "0C", Integer.toString(len), 10);
            }
        }catch (Exception e){
            e.printStackTrace();

            redisUtil.hset(clientId,"0C", "0", 10);
            CollectorInfo info = collectorInfoService.selectCollectorInfoById(clientId);

            AsyncManager.me().execute(AlarmPoolTask.saveAlarm(clientId, String.valueOf(info.getLocationId()),"3", "3", "获取采集器关联设备", "采集器"+clientId+"数据["+datas+"]有误，解析错误"+e.getMessage()));
        }
    }

    /**
     * 将阀门和热表登记为未登记状态
     * @param clientId
     */
    private static void saveInit(String clientId){
        //还原阀门登记状态
        valveInfoService.updateValveInfoByCollectorId(clientId);
        //还原热表登记状态
        meterInfoService.updateMeterInfoByCollectorId(clientId);
    }
}